package com.example.fileuploaddownload.controller;

import com.example.fileuploaddownload.entity.FileEntity;
import com.example.fileuploaddownload.service.FileService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * 文件控制器
 * 处理文件上传、下载、查询等HTTP请求
 */
@Slf4j
@Controller
public class FileController {

    @Autowired
    private FileService fileService;

    /**
     * 首页路由
     * 显示文件上传下载界面
     */
    @GetMapping("/")
    public String index(Model model) {
        // 获取所有已上传的文件列表
        model.addAttribute("files", fileService.listFiles());
        return "index";
    }

    /**
     * 清理已上传的文件分片
     * 当用户取消上传时，用于清理临时分片文件和数据库记录
     */
    @PostMapping("/cleanup-chunks")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> cleanupChunks(@RequestBody Map<String, String> requestBody) {
        Map<String, Object> result = new HashMap<>();
        try {
            String identifier = requestBody.get("identifier");
            if (identifier == null || identifier.isEmpty()) {
                result.put("success", false);
                result.put("message", "缺少文件标识符参数");
                return ResponseEntity.badRequest().body(result);
            }
            
            log.info("清理分片文件: identifier={}", identifier);
            fileService.cleanupChunks(identifier);
            
            result.put("success", true);
            result.put("message", "分片清理成功");
            return ResponseEntity.ok(result);
        } catch (Exception e) {
            log.error("清理分片失败: {}", e.getMessage(), e);
            result.put("success", false);
            result.put("message", "分片清理失败: " + e.getMessage());
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
        }
    }

    /**
     * 文件上传接口（支持断点续传）
     * 使用POST请求处理文件分片上传
     */
    /**
     * 取消上传接口
     * 清理已上传的分片数据
     */
    @PostMapping("/cancel-upload")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> cancelUpload(@RequestBody Map<String, String> request) {
        Map<String, Object> result = new HashMap<>();
        try {
            String identifier = request.get("identifier");
            if (identifier == null || identifier.isEmpty()) {
                result.put("success", false);
                result.put("message", "缺少文件标识符");
                return ResponseEntity.badRequest().body(result);
            }
            
            // 调用服务层清理分片数据
            fileService.cleanupUploadChunks(identifier);
            
            result.put("success", true);
            result.put("message", "上传取消成功，已清理分片数据");
            return ResponseEntity.ok(result);
        } catch (Exception e) {
            log.error("取消上传失败: {}", e.getMessage(), e);
            result.put("success", false);
            result.put("message", "取消上传失败: " + e.getMessage());
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
        }
    }
    
    @PostMapping("/upload")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> upload(@RequestParam("file") MultipartFile file,
                                                     @RequestParam(value = "chunkIndex", required = false) Integer chunkIndex,
                                                     @RequestParam(value = "totalChunks", required = false) Integer totalChunks,
                                                     @RequestParam(value = "identifier", required = false) String identifier) {
        Map<String, Object> result = new HashMap<>();
        try {
            // 更健壮的参数检查，适应暂停/继续上传场景
            if (chunkIndex == null || totalChunks == null || identifier == null) {
                // 记录详细的参数缺失信息以便调试
                log.warn("文件上传参数不完整 - chunkIndex: {}, totalChunks: {}, identifier: {}", 
                         chunkIndex, totalChunks, identifier);
                
                if (chunkIndex == null) {
                    result.put("message", "缺少分片索引参数");
                } else if (totalChunks == null) {
                    result.put("message", "缺少总分片数参数");
                } else {
                    result.put("message", "缺少文件标识符参数");
                }
                result.put("success", false);
                return ResponseEntity.badRequest().body(result);
            }
            
            log.info("接收文件分片: {}, 总分片: {}, 标识符: {}", chunkIndex, totalChunks, identifier);
            
            // 检查文件是否为空
            if (file.isEmpty()) {
                result.put("success", false);
                result.put("message", "文件不能为空");
                return ResponseEntity.badRequest().body(result);
            }

            // 调用服务层上传文件分片
            FileEntity fileEntity = fileService.uploadFile(file, chunkIndex, totalChunks, identifier);
            
            result.put("success", true);
            result.put("message", "文件分片上传成功");
            if (fileEntity != null) {
                result.put("fileId", fileEntity.getId());
                result.put("progress", fileEntity.getUploadProgress());
            }
            return ResponseEntity.ok(result);
        } catch (Exception e) {
            log.error("文件分片上传失败: {}", e.getMessage(), e);
            result.put("success", false);
            result.put("message", "文件分片上传失败: " + e.getMessage());
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
        }
    }

    /**
     * 文件分片合并接口
     * 用于合并已上传的文件分片
     */
    @PostMapping("/merge")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> merge(@RequestParam("identifier") String identifier,
                                                   @RequestParam("fileName") String fileName,
                                                   @RequestParam("contentType") String contentType) {
        Map<String, Object> result = new HashMap<>();
        try {
            log.info("合并文件分片: {}, 文件名: {}", identifier, fileName);
            
            // 调用服务层合并文件分片
            FileEntity fileEntity = fileService.mergeChunks(identifier, fileName, contentType);
            
            result.put("success", true);
            result.put("message", "文件合并成功");
            result.put("fileId", fileEntity.getId());
            return ResponseEntity.ok(result);
        } catch (Exception e) {
            log.error("文件分片合并失败: {}", e.getMessage(), e);
            result.put("success", false);
            result.put("message", "文件分片合并失败: " + e.getMessage());
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
        }
    }

    /**
     * 检查文件是否已存在接口
     * 用于检测文件是否已上传过，避免重复上传
     */
    @GetMapping("/check")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> checkFile(@RequestParam("identifier") String identifier) {
        Map<String, Object> result = new HashMap<>();
        try {
            boolean exists = fileService.checkFileExists(identifier);
            result.put("success", true);
            result.put("exists", exists);
            
            // 如果文件已存在，返回文件信息
            if (exists) {
                FileEntity fileEntity = fileService.getFileByMd5(identifier);
                result.put("fileId", fileEntity.getId());
                result.put("fileName", fileEntity.getOriginalName());
                result.put("fileSize", fileEntity.getFileSize());
            } else {
                // 如果文件不存在，检查已上传的分片
                int[] uploadedChunks = fileService.checkUploadedChunks(identifier);
                result.put("uploadedChunks", uploadedChunks);
            }
            
            return ResponseEntity.ok(result);
        } catch (Exception e) {
            log.error("检查文件失败: {}", e.getMessage(), e);
            result.put("success", false);
            result.put("message", "检查文件失败: " + e.getMessage());
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
        }
    }

    /**
     * 计算文件MD5接口
     * 前端上传前计算文件MD5，用于断点续传和文件去重
     */
    @PostMapping("/calculate-md5")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> calculateMd5(@RequestParam("file") MultipartFile file) {
        Map<String, Object> result = new HashMap<>();
        try {
            String md5 = fileService.calculateFileMd5(file);
            result.put("success", true);
            result.put("md5", md5);
            return ResponseEntity.ok(result);
        } catch (Exception e) {
            log.error("计算文件MD5失败: {}", e.getMessage(), e);
            result.put("success", false);
            result.put("message", "计算文件MD5失败: " + e.getMessage());
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
        }
    }

    /**
     * 文件下载接口（支持断点续传）
     * 使用GET请求处理文件下载
     */
    @GetMapping("/download/{fileId}")
    public void download(@PathVariable("fileId") Long fileId, HttpServletRequest request, HttpServletResponse response) {
        try {
            log.info("下载文件: {}", fileId);
            fileService.downloadFile(fileId, request, response);
        } catch (IOException e) {
            log.error("文件下载失败: {}", e.getMessage(), e);
            try {
                response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "文件下载失败");
            } catch (IOException ex) {
                log.error("发送错误响应失败", ex);
            }
        }
    }

    /**
     * 删除文件接口
     * 使用DELETE请求删除文件
     */
    @DeleteMapping("/file/{fileId}")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> delete(@PathVariable("fileId") Long fileId) {
        Map<String, Object> result = new HashMap<>();
        try {
            log.info("删除文件: {}", fileId);
            boolean success = fileService.deleteFile(fileId);
            if (success) {
                result.put("success", true);
                result.put("message", "文件删除成功");
                return ResponseEntity.ok(result);
            } else {
                result.put("success", false);
                result.put("message", "文件不存在或删除失败");
                return ResponseEntity.badRequest().body(result);
            }
        } catch (Exception e) {
            log.error("文件删除失败: {}", e.getMessage(), e);
            result.put("success", false);
            result.put("message", "文件删除失败: " + e.getMessage());
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
        }
    }

    /**
     * 文件列表接口
     * 获取所有已上传的文件列表
     */
    @GetMapping("/files")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> listFiles() {
        Map<String, Object> result = new HashMap<>();
        try {
            result.put("success", true);
            result.put("files", fileService.listFiles());
            return ResponseEntity.ok(result);
        } catch (Exception e) {
            log.error("获取文件列表失败: {}", e.getMessage(), e);
            result.put("success", false);
            result.put("message", "获取文件列表失败: " + e.getMessage());
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
        }
    }
}